#include "WebsocketClient.h"
#include <iostream>


WebsocketClient::WebsocketClient() {}
WebsocketClient::~WebsocketClient(){}


void WebsocketClient::on_message(websocketpp::connection_hdl hdl, message_ptr msg) {
	// std::cout << msg->get_payload() << std::endl;
    m_receive_handler(msg->get_payload());
}

int WebsocketClient::open(std::string uri)
{
    int ret = 0;
    // 调整日志策略
    echo_client.clear_access_channels( websocketpp::log::alevel::frame_header );
    echo_client.clear_access_channels( websocketpp::log::alevel::frame_payload );

    try {
        // 初始化ASIO ASIO
        echo_client.init_asio();
 
        // 注册回调函数
        echo_client.set_open_handler( std::bind( &WebsocketClient::on_open, this ));
        // echo_client.set_fail_handler( std::bind( &on_fail, &echo_client, ::_1 ));
        echo_client.set_message_handler(std::bind(&WebsocketClient::on_message, this, ::_1, ::_2));
        echo_client.set_close_handler( std::bind( &WebsocketClient::on_close, this ));
 
        // 在事件循环启动前创建一个连接对象
        websocketpp::lib::error_code ec;
        con = echo_client.get_connection( uri, ec );
        echo_client.connect( con );
        con->get_handle(); // 连接句柄，发送消息时必须要传入
        this->uri = uri;
        // 启动事件循环（ASIO的io_service），当前线程阻塞
        echo_client.run();
    } catch ( const std::exception &e ) {
        std::cout << e.what() << std::endl;
        ret = -1;
    } catch ( websocketpp::lib::error_code e ) {
        std::cout << e.message() << std::endl;
        ret = -1;
    } catch ( ... ) {
        std::cout << "other exception" << std::endl;
        ret = -1;
    }

    return ret;
}

int WebsocketClient::close()
{
    int ret = 0;
	try {
		if (con!= NULL && con->get_state() == websocketpp::session::state::value::open)
		{
			websocketpp::close::status::value cvValue = 0;
			std::string strReason = "";
			con->close(cvValue, strReason);
		}
	}
	catch (websocketpp::exception const & e)
	{
		ret = -1;
	}

    return ret;
}

// - Private 
void WebsocketClient::on_open()
{
    std::cout << "connection on_open" << std::endl;
    is_connect = true;
}

void WebsocketClient::on_close()
{
    std::cout << "on_close" << std::endl;
    is_connect = false;
}

int WebsocketClient::sendBinaryData(Data data, size_t size)
{
    int ret = 0;
    try
    {
        websocketpp::lib::error_code ec;
        ec = con->send(data,size,websocketpp::frame::opcode::BINARY);
        if (ec) {
            std::cout << "Echo failed because: " << ec.message() << std::endl;
			ret = -1;
        }
    }
    catch(websocketpp::exception const & e)
    {
        std::cerr << e.what() << '\n';
        return -2;
    }
    
    return ret;
}

int WebsocketClient::sendTextData(char *text)
{
    int nRet = 0;
	try {
		websocketpp::lib::error_code ec;
    
		ec = con->send(text);
		if (ec) {
			std::cout << "Echo failed because: " << ec.message() << std::endl;
			nRet = -1;
		}
	}
	catch (websocketpp::exception const & e) {
		std::cout << e.what() << std::endl;
		return -2;
	}

	return nRet;
}
